package com.yfjin.camera2;

import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.util.Log;
import android.util.Size;
import android.view.TextureView;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.ByteBuffer;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity implements Camera2Helper.Camera2Listener {


    TextureView textureView;
    private boolean isStop=false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        File file = new File(Environment.getExternalStorageDirectory() + "/aaa.h264");
        if (file.exists()) {
            file.delete();
        }
        File file2 = new File(Environment.getExternalStorageDirectory() + "/aaa.txt");
        if (file2.exists()) {
            file2.delete();
        }

        textureView = findViewById(R.id.texture);

        textureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
            @Override
            public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
                initCamera();
            }

            @Override
            public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {

            }

            @Override
            public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
                return false;
            }

            @Override
            public void onSurfaceTextureUpdated(SurfaceTexture surface) {

            }
        });


//        new Handler().postDelayed(new Runnable() {
//            @Override
//            public void run() {
//                stopMedia();
//            }
//        }, 10000);
    }

    private void stopMedia() {
        isStop=true;
        mediaCodec.stop();
        mediaCodec.release();
        mediaCodec=null;
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                System.exit(0);
            }
        }, 2000);
    }


    private void initCamera() {
        Camera2Helper helper = new Camera2Helper(this, this);
        try {
            helper.start(textureView);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }


    byte[] nv12;
    byte[] nv21;
    byte[] nv21_rotated;


    int incount=0;
    int outcount=0;
    @Override
    public void onPreview(byte[] y, byte[] uv, byte[] vu, Size previewSize, int stride) {

        if (isStop){
            return;
        }

        if (nv21 == null) {
//            实例化了一次
            int size = stride * previewSize.getHeight() * 3 / 2;
            nv21 = new byte[size];
            nv21_rotated = new byte[size];
        }

//        ImageUtil.yuv888ToNv12_0(y, uv, vu, nv21, stride, previewSize.getHeight());
        ImageUtil.yuv888ToNv12_1(y, uv, vu, nv21, stride, previewSize.getHeight());
//        ImageUtil.nv21_rotate_to_90(nv21, nv21_rotated, stride, previewSize.getHeight());
//        byte[] temp = ImageUtil.nv21toNV12(nv21_rotated, nv12);
//        byte[] temp = ImageUtil.nv21toNV12(nv21, nv12);
        ;
//        byte[] temp = ImageUtil.ni(stride,previewSize.getHeight(),nv21);
//        byte[] temp= nv21_rotated;
        byte[] temp= nv21;

        if (mediaCodec == null) {
            initCodec(stride, previewSize);
        }

        MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
        int inIndex = mediaCodec.dequeueInputBuffer(10000);
        Log.i("333","inindex:"+(incount++)+"==="+inIndex);
        if (inIndex >= 0) {

            ByteBuffer byteBuffer = mediaCodec.getInputBuffer(inIndex);
            byteBuffer.clear();
            byteBuffer.put(temp, 0, temp.length);
            mediaCodec.queueInputBuffer(inIndex, 0, temp.length,
                    0, 0);
        }
        int outIndex = mediaCodec.dequeueOutputBuffer(info, 100*1000);
        Log.i("333","outIndex:"+(outcount++)+"==="+outIndex);
        while (outIndex >= 0) {
            Log.i("333","1");
            ByteBuffer byteBuffer = mediaCodec.getOutputBuffer(outIndex);
            Log.i("333","2");
            byte[] ba = new byte[byteBuffer.remaining()];
            Log.i("333","3");
            byteBuffer.get(ba);
            Log.i("333","4");
            writeContent(ba);
            writeBytes(ba);
            mediaCodec.releaseOutputBuffer(outIndex, false);
            outIndex = mediaCodec.dequeueOutputBuffer(info, 10000);
            Log.i("333","5");
        }
        Log.i("333","6666");
    }

    private MediaCodec mediaCodec;

    private void initCodec(int stride, Size size) {
        try {
            mediaCodec = MediaCodec.createEncoderByType("video/avc");

            final MediaFormat format = MediaFormat.createVideoFormat("video/avc",
//                    size.getHeight(), stride);
//                    size.getHeight(), size.getWidth());
                    stride, size.getHeight());
            //设置帧率  手动触发一个I帧
            format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
                    MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible);
            format.setInteger(MediaFormat.KEY_FRAME_RATE, 15);//15*2 =30帧
            format.setInteger(MediaFormat.KEY_BIT_RATE, 4000_000);
            format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 2);//2s一个I帧，也就是15*2=30帧一个I帧
            mediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
            mediaCodec.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void writeBytes(byte[] array) {
        FileOutputStream writer = null;
        try {
            // 打开一个写文件器，构造函数中的第二个参数true表示以追加形式写文件
            writer = new FileOutputStream(Environment.getExternalStorageDirectory() + "/aaa.h264", true);
            writer.write(array);
            writer.write('\n');

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (writer != null) {
                    writer.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public   String writeContent(byte[] array) {
        char[] HEX_CHAR_TABLE = {
                '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
        };
        StringBuilder sb = new StringBuilder();
        for (byte b : array) {
            sb.append(HEX_CHAR_TABLE[(b & 0xf0) >> 4]);
            sb.append(HEX_CHAR_TABLE[b & 0x0f]);
        }
        Log.i("333", "writeContent: "+sb.toString());
        FileWriter writer = null;
        try {
            // 打开一个写文件器，构造函数中的第二个参数true表示以追加形式写文件
            writer = new FileWriter(Environment.getExternalStorageDirectory()+"/aaa.txt", true);
            writer.write(sb.toString());
            writer.write("\n");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if(writer != null){
                    writer.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return sb.toString();
    }

}